<?php

namespace App\Listeners;

use App\Repository\Models\Orders;
use App\Repository\Repositories\Interfaces\OrdersCrontabRepository;
use App\Repository\Repositories\OrderProductsRepositoryEloquent;
use App\Repository\Repositories\OrdersCrontabRepositoryEloquent;
use App\Repository\Repositories\OrdersRepositoryEloquent;
use App\Repository\Repositories\ProductSkusRepositoryEloquent;
use App\Repository\Repositories\ProductsRepositoryEloquent;
use App\Services\Pay\CzbankService;
use Mockery\Exception;

class OrderListener
{
    private $orders_repo;
    private $order_products_repo;
    private $product_skus_repo;
    private $products_repo;
    private $orders_crontab_repo;

    public function __construct(OrdersRepositoryEloquent $orders_repo,
                                OrderProductsRepositoryEloquent $order_products_repo,
                                ProductSkusRepositoryEloquent $product_skus_repo,
                                ProductsRepositoryEloquent $product_repo,
                                OrdersCrontabRepositoryEloquent $orders_crontab_repo)
    {
        $this->orders_repo = $orders_repo;
        $this->order_products_repo = $order_products_repo;
        $this->product_skus_repo = $product_skus_repo;
        $this->products_repo = $product_repo;
        $this->orders_crontab_repo = $orders_crontab_repo;
    }

    public function subscribe($events)
    {
        $events->listen(
            'App\Events\OrderAffirmEvent',
            'App\Listeners\OrderListener@affirm'
        );
        $events->listen(
            'App\Events\OrderCancelEvent',
            'App\Listeners\OrderListener@cancel'
        );
    }

    /**
     * @param $event:data['order_id']
     * @return bool
     */
    public function affirm($event)
    {
        $data = $event->data;
        $update = [
            'order_status' => Orders::ORDER_STATUS_AFFIRM
        ];

        //获取订单信息
        $order = $this->orders_repo->with(['receivingAccount'])->find($data['order_id']);
        $trade_no = $order['data']['trade_no'];
        $czbank_no = array_get($order['data'], 'receiving_account.czbank_no');
        $order_money = $order['data']['order_money'];

        //通知浙商放款
        if ($trade_no && $czbank_no && $order_money) {
            $czbank_service = new CzbankService();
            $loan_ret = $czbank_service->loan($trade_no, $czbank_no, $order_money);
            if($loan_ret){
                $update['receivable_at'] = date('Y-m-d H:i:s', time());
                $update['receivable_type'] = Orders::RECEIVABLE_TYPE_RECEIVED;
            }
        }

        \DB::beginTransaction();
        try{
            //更新订单状态
            $order = $this->orders_repo->update($update, $data['order_id']);
            $order_code = array_get($order['data'], 'order_code');

            //更新产品销售数量
            $order_products = $this->order_products_repo->findWhere(['order_code' => $order_code]);
            foreach($order_products['data'] as $order_product){
                $this->products_repo->increment('succ_num', ['id' => $order_product['product_id']]);
            }

            //更新定时任务记录表
            $this->orders_crontab_repo->affirmDone($data['order_id']);

            \DB::commit();
            $ret = true;
        }catch(Exception $e){
            \DB::rollback();
            $ret = false;
        }

        return $ret ? true : false;
    }

    /**
     * @param $event:data['order_id']
     * @return bool
     */
    public function cancel($event)
    {
        $data = $event->data;
        $update = [
            'order_status' => Orders::ORDER_STATUS_CANCEL
        ];

        \DB::beginTransaction();
        try{
            //取消订单
            $order = $this->orders_repo->update($update, $data['order_id']);
            $order_code = array_get($order['data'], 'order_code');

            //退还库存
            $order_products = $this->order_products_repo->findWhere(['order_code' => $order_code]);
            foreach($order_products['data'] as $order_product){
                $this->product_skus_repo->incrementStock($order_product['sku_id'], $order_product['quantity']);
            }

            //更新定时任务记录表
            $this->orders_crontab_repo->cancelDone($data['order_id']);

            \DB::commit();
            $ret = true;
        }catch(Exception $e){
            \DB::rollback();
            $ret = false;
        }

        return $ret;
    }
}
